use anyhow::{bail, Result};
use quick_xml::de::from_str;
use serde::Deserialize;
use std::{fs::File, io::Read, path::Path};

#[derive(Deserialize, Default, Debug)]
pub struct Repomd {
    revision: u64,
    #[serde(rename = "$value")]
    datas: Vec<Data>, // files: Files,
}
impl Repomd {
    pub fn get_primary_location(&self) -> &str {
        self.datas
            .iter()
            .find(|x| x.r#type == "primary")
            .unwrap()
            .location
            .href
            .as_str()
    }
    pub fn get_primary_size(&self) -> u64 {
        self.datas
            .iter()
            .find(|x| x.r#type == "primary")
            .unwrap()
            .size
    }
    pub fn parse_from<P: AsRef<Path>>(path: P) -> Result<Self> {
        let mut f = File::open(path.as_ref())?;
        let mut buf = String::new();
        f.read_to_string(&mut buf)?;
        match from_str::<Repomd>(buf.as_str()) {
            Ok(repomd) => return Ok(repomd),
            Err(e) => {
                bail!("Failed to parse {:?} {} \n {}", path.as_ref(), e, buf)
            }
        }
    }
}

#[derive(Deserialize, Default, Debug)]
struct Data {
    #[serde(rename = "@type")]
    r#type: String,
    #[serde(rename = "checksum")]
    checksum: CheckSum,
    location: Location,
    timestamp: u64,
    size: u64,
}
#[derive(Deserialize, Default, Debug)]
struct CheckSum {
    #[serde(rename = "@type")]
    r#type: String,
    #[serde(rename = "$value")]
    checksum: String,
}
#[derive(Deserialize, Default, Debug)]
struct Location {
    #[serde(rename = "@href")]
    href: String,
}
#[test]
fn test_repomd() {
    let mut f = File::open("assest/repomd.xml").unwrap();
    let mut buf = String::new();
    f.read_to_string(&mut buf).unwrap();
    let repo = from_str::<Repomd>(buf.as_str()).unwrap();
    dbg!(repo);
}
